package com.example.demo.filters;

import com.example.demo.util.JwtUtilsSelf;
import com.example.demo.service.RedisService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    @Autowired
    private JwtUtilsSelf jwtUtilsSelf;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private RedisService redisService;

    @Value("${jwt.header}")
    private String authorizationHeader;

    @Value("${jwt.prefix}")
    private String tokenPrefix;

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {
        // 获取请求头中的Authorization字段
        final String header = request.getHeader(authorizationHeader);
        String url = request.getRequestURI();
        logger.info("request.getRequestURI()", url);
        logger.info("request.getRequestURI()", header);
        System.out.println("原始请求URI: " + request.getRequestURI());

        List<String> whiteList = List.of("/api/auth/login", "/api/auth/register");
        boolean isCts = whiteList.contains(request.getRequestURI());

        if (isCts) {
            filterChain.doFilter(request, response);
            return;
        }

        logger.info(request.getPathInfo());

        // 如果请求头中没有Authorization字段或者不是以Bearer开头，直接放行
        if (header == null || !header.startsWith(tokenPrefix + " ")) {
            filterChain.doFilter(request, response);
            return;
        }


        // 提取JWT令牌（去掉Bearer前缀）
        final String token = header.substring(tokenPrefix.length() + 1);

        logger.info("token : token token" + token);

        // 从JWT中提取用户名
        final String username = jwtUtilsSelf.extractUsername(token);

        logger.warn("username : " + username);
        logger.warn("auth.info : " + SecurityContextHolder.getContext().getAuthentication());

        // 如果用户名不为空且当前SecurityContext中没有认证信息
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            // 从数据库中加载用户信息
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            System.out.println(userDetails);
            System.out.println("userDetails JWT");
            System.out.println("userDetails JWT");

            // 验证JWT令牌是否有效且在Redis中存在
            if (jwtUtilsSelf.isTokenValid(token, userDetails) && redisService.validateToken(username, token)) {
                // 创建认证对象
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );
                authToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                // 将认证信息设置到SecurityContext中
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }

        // 继续执行过滤器链
        filterChain.doFilter(request, response);
    }
}